/*
 * MuxerFileMediaSink.cpp
 *
 *  Created on: 2020年8月11日
 *      Author: chuan
 */

#include "MuxerFileMediaSink.h"
#include <string>
#include "TFileWriter.h"
#include <functional>
#include <atomic>


class MuxerFileMediaSinkPrivate
{
public:
    MuxerFileMediaSinkPrivate():
		m_opened()
    {
    }

    ~MuxerFileMediaSinkPrivate()
    {
        close();
    }

    bool open(const char* filepath)
    {
        bool done = m_writer.open(filepath, "wb");
		m_opened = done;
		return done;
    }

    bool isOpen()
    {
        return m_opened;
    }

    void close()
    {
		m_opened = false;
        m_writer.close();
    }

    void write(UMediaPacket& pkt)
    {
		if (!m_opened)
		{
			return;
		}

        m_writer.write(pkt.data(), pkt.size());
    }

    comn::FileWriter    m_writer;
    std::string			m_filePath;
	std::atomic_bool	m_opened;

};


MuxerFileMediaSink::MuxerFileMediaSink(UMediaMuxer* muxer):
    m_muxer(),
    m_pimpl(new MuxerFileMediaSinkPrivate())
{
    setMuxer(muxer);
}

MuxerFileMediaSink::~MuxerFileMediaSink()
{
    close();

    delete m_pimpl;
}

bool MuxerFileMediaSink::open(const char* filepath)
{
    bool done = m_pimpl->open(filepath);
    return done;
}

void MuxerFileMediaSink::close()
{
    m_pimpl->close();

	if (m_muxer)
	{
		UMediaMuxer::Sink sink;
		m_muxer->setSink(sink);

		m_muxer = nullptr;
	}
}

bool MuxerFileMediaSink::isOpen()
{
    return m_pimpl->isOpen() && m_muxer;
}

bool MuxerFileMediaSink::setFile(const char* filename)
{
	return false;
}

const char* MuxerFileMediaSink::getFile()
{
    return m_pimpl->m_filePath.c_str();
}

void MuxerFileMediaSink::onMediaFormat(const UMediaFormat& fmt)
{
	if (!m_muxer)
	{
		return;
	}

    m_muxer->open(fmt);
}

void MuxerFileMediaSink::onMediaPacket(UMediaPacket& pkt)
{
	if (!m_muxer)
	{
		return;
	}

    m_muxer->input(pkt);
}

void MuxerFileMediaSink::onMediaEvent(int event)
{
    //
}

void MuxerFileMediaSink::onMuxer(UMediaPacket& pkt)
{
    m_pimpl->write(pkt);
}

void MuxerFileMediaSink::setMuxer(UMediaMuxer* muxer)
{
    m_muxer = muxer;

    if (m_muxer)
    {
        UMediaMuxer::Sink sink = std::bind(&MuxerFileMediaSink::onMuxer, this, std::placeholders::_1);
        m_muxer->setSink(sink);
    }
}
